(function(angular) {
	"use strict";
	angular.module("fs.waf").factory("loanService", loanService);
	loanService.$inject = [ "$q", "ajaxServiceFactory", "modalService", "arithService", "dateService", "txnService", "commonService" ];
	function loanService($q, ajaxServiceFactory, modalService, arithService, dateService, txnService, commonService) {
		var loanStatusOptions = [ {
			"value" : "L",
			"label" : "label.settlement.summary.entered"
		}, {
			"value" : "N",
			"label" : "label.settlement.summary.disbursed"
		}, {
			"value" : "P",
			"label" : "label.settlement.summary.pastdue"
		}, {
			"value" : "X",
			"label" : "label.settlement.summary.canceled"
		}, {
			"value" : "Q",
			"label" : "label.settlement.summary.liquated"
		}, {
			"value" : "F",
			"label" : "label.settlement.summary.closed"
		}];
		// loan log page start
		function createInitOptionData() {
			var ajaxServices = ajaxServiceFactory.buildAjaxService({
				getLoanCreateOptions : {
					url : "do/cls/dataList/getLoanCreateOptions",
					method : "get"
				}
			});
			var defer = $q.defer();
			ajaxServices.getLoanCreateOptions().then(function(response) {
				defer.resolve(response.data);
			});
			return defer.promise;
		}
		
		function getApCommunity(communityId){
			var ajaxServices = ajaxServiceFactory.buildAjaxService({
				getApCommunity : {
					url : "do/cda/apCommunity/getApCommunityByPk",
					method : "get"
				}
			});
			var defer = $q.defer();
			ajaxServices.getApCommunity({"communityId" : communityId}).then(function(response) {
				defer.resolve(response.data);
			});
			return defer.promise;
		}

		function getProdCodeChangedData(param) {
			var ajaxServices = ajaxServiceFactory.buildAjaxService({
				getProdCodeChangedOptions : {
					url : "do/cls/dataList/loanCreateProdCodeChanged",
					method : "get"
				}
			});
			var defer = $q.defer();
			ajaxServices.getProdCodeChangedOptions(param).then(function(response) {
				defer.resolve(response.data);
			});
			return defer.promise;
		}
		// loan log page end

		// loan logged update page start
		function loggedUpdateInitOptionData() {
			var ajaxServices = ajaxServiceFactory.buildAjaxService({
				loggedUpdateInitOptionData : {
					url : "do/cls/dataList/getLoanCreateOptions",
					method : "get"
				}
			});
			var defer = $q.defer();
			ajaxServices.loggedUpdateInitOptionData().then(function(response) {
				defer.resolve(response.data);
			});
			return defer.promise;
		}
		// loan logged update page end
		
		function getLoanUpdateOptions() {
			var ajaxServices = ajaxServiceFactory.buildAjaxService({
				getLoanUpdateOptions : {
					url : "do/cls/dataList/getLoanUpdateOptions",
					method : "get"
				}
			});
			var defer = $q.defer();
			ajaxServices.getLoanUpdateOptions().then(function(response) {
				defer.resolve(response.data);
			});
			return defer.promise;
		}

		function resetIntAndPastdueTableReadonly(ctrl) {
			if (ctrl.loan.prodSubType) {
				// reset loanInt table
				var flag = ctrl.loan.prodSubType.utIntTier == "N" ? false : true;
				angular.forEach(ctrl.loan.loanIntObject, function(loanInt, index) {
					var intCat = index;
					angular.forEach(ctrl.spreadTierInnerGridOptions[intCat].columnDefs, function(colDef, index) {
						colDef.readonly = !flag;
					});
					ctrl.spreadTierInnerGridOptions[intCat].enableOperationAdd = flag;
					ctrl.spreadTierInnerGridOptions[intCat].enableOperationRemoveSelected = flag;
					ctrl.spreadTierInnerGridOptions[intCat].enableOperationAddSubRow = flag;
				});
				// reset pastdue table
				angular.forEach(ctrl.pastdueInnerGridOptions.columnDefs, function(colDef, index) {
					if (ctrl.loan.prodSubType.utPastdueSchd == "N") {
						colDef.readonly = true;
					} else {
						if (colDef.model != "pastdueTenorFrom") {
							colDef.readonly = false;
						}
					}
				});

				if (ctrl.loan.prodSubType.upIntCalcBases) {
					var filterOptions = [];
					for (var i = 0; i < ctrl.loan.allIntCalcBasisOptions.length; i++) {
						var loadVal = ctrl.loan.allIntCalcBasisOptions[i].value;
						if (ctrl.loan.prodSubType.upIntCalcBases.indexOf(loadVal) >= 0) {
							filterOptions[filterOptions.length] = ctrl.loan.allIntCalcBasisOptions[i];
						}
					}
					ctrl.intCalcBasisOptions = filterOptions;
				}

			}
		}

		function getLoanUpdateProdCodeOptionData(prodSubtype) {
			var ajaxServices = ajaxServiceFactory.buildAjaxService({
				getLoanUpdatepProdCodeOptions : {
					url : "do/cls/dataList/getLoanUpdateProdCodeOptions",
					method : "get"
				}
			});
			var defer = $q.defer();
			var param = {
				"prodSubType" : prodSubtype
			};
			ajaxServices.getLoanUpdatepProdCodeOptions(param).then(function(response) {
				defer.resolve(response.data);
			});
			return defer.promise;
		}

		// loan update page end
		function getLayout(prodType, prodSubtype, packageName, packageSuffix, readonly) {
			if (prodType && prodSubtype) {
				return txnService.getLayout(packageName, packageSuffix, readonly, "LOAN", prodType, prodSubtype);
			} else {
				return $q(function(resolved, rejected) {
					resolved(undefined);
				});
			}
		}

		function deleteDynaparm(layoutConfig) {
			if (layoutConfig) {
				if (layoutConfig.formConfigs && layoutConfig.formConfigs.general) {
					var gridConfigs = layoutConfig.formConfigs.general.gridConfigs;
					txnService.deleteDynaparm(gridConfigs);
				}
			}
			return layoutConfig;
		}
		/** ******************** Interest ************************** */

		function getLoanListOptions() {
			var ajaxServices = ajaxServiceFactory.buildAjaxService({
				getLoanListOptions : {
					url : "do/cls/dataList/getLoanListOptions",
					method : "get"
				}
			});
			var defer = $q.defer();
			ajaxServices.getLoanListOptions().then(function(response) {
				defer.resolve(response ? response.data : {});
			});
			return defer.promise;

		}

		/**
		 * 1.bill freq new must be greater than 0(Has exist in fw validation)
		 * 2.Bill First On Date should be equal to or greater than Effective
		 * Date. 3.billFirstOnNew should be after the lock days period
		 * 4.billFirstOnNew should be 1 to 28 when frequency type is M/Q and
		 * billEndOfMonth is No 5.billFirstOnNew should not be before the last
		 * bill date propertyObj.billTotalAmt = ctrl.loan.loanBill.billTotalAmt;
		 * propertyObj.billPrincFlag = ctrl.loan.loanBill.billPrincFlag;
		 * propertyObj.billPrincAmt = ctrl.loan.loanBill.billPrincAmt; TODO this
		 * want all in fw validation
		 */
		function validateBilling(loan, messages) {
			if (loan.loanInfo.billingFlag != "Y") {
				return;
			}
			var billFreqNew = loan.loanBill.billFreq;
			var billFirstOnNew = loan.loanBill.billFirstOn;
			var effectiveDate = loan.loanInfo.effectiveDate;
			var lockDays = loan.loanInfo.lockDays;
			var billFreqTypeNew = loan.loanBill.billFreqType;
			var billOnEomNew = loan.loanBill.billOnEomFlag;
			var nextBillDate = loan.loanExt.nextBillDate;
			var numBills = loan.loanExt.numBills;
			var billTotalAmt = loan.loanBill.billTotalAmt;
			var billPrincFlag = loan.loanBill.billPrincFlag;
			var billPrincAmt = loan.loanBill.billPrincAmt;

			if (!billFreqNew || billFreqNew * 1 == 0) {
				messages.push("error.info.billing-frequency");
			}

			if (!billFreqTypeNew) {
				messages.push("error.info.billing-frequencytype-required");
			}

			if (!billFirstOnNew) {
				messages.push("error.info.billing-firston-required");
			}

			if (!billTotalAmt) {
				messages.push("error.info.totalamountgreaterequalzero");
			}

			if (billPrincFlag == "Y" && (!billPrincAmt || billPrincAmt * 1 == 0)) {
				messages.push("error.info.principalamountgreaterequalone");
			}

			// Bill First On Date should be equal to or greater than Effective
			// Date
			if (billFirstOnNew && effectiveDate && dateService.compareDate(billFirstOnNew, effectiveDate) > 0) {
				messages.push("error.info.billfirstondate-effectivedate");
			}

			// billFirstOnNew should be after the lock days period
			var effectiveDateTmp = angular.copy(effectiveDate);
			var loanLockEndDate = dateService.addDays(effectiveDateTmp, lockDays);
			if (billFirstOnNew && loanLockEndDate && dateService.compareDate(billFirstOnNew, loanLockEndDate) > 0) {
				messages.push("error.info.billfirstondate-lockperiod");
			}

			// the bill first on should be 1 to 28 when frequency type is M/Q
			// and billEndOfMonth is No
			if ("M" == billFreqTypeNew || "Q" == billFreqTypeNew) {
				if (billOnEomNew == "N") {
					// the billFirstOnNew will be in 1 to 28 when endOfMonth
					// isn"t checked
					if (billFirstOnNew && billFirstOnNew.getDate() > 28) {
						messages.push("error.info.billfirstondate-limit");
					}
				}
			}

			// the bill first on should not be before the last billing date(the
			// number of bill must > 0)
			if (nextBillDate != "" && numBills * 1 > 0 && billFirstOnNew && dateService.compareDate(billFirstOnNew, nextBillDate) > 0) {
				messages.push("error.info.billfirstondate-nextbilldate");
			}
		}

		function dateChanged(loan) {
			if (loan.loanInfo && loan.loanInfo.effectiveDate && loan.loanInfo.maturityDate) {
				var days = dateService.compareDate(loan.loanInfo.effectiveDate, loan.loanInfo.maturityDate);
				if (days < 0) {
					modalService.openErrorDialogs({
						messages : [ "error.info.maturitydate-effectivedate" ]
					});
					return;
				} else {
					loan.loanInfo.tenorDays = days;
				}
			}
		}

		function tenorDaysChanged(loan) {
			if (loan.loanInfo && loan.loanInfo.tenorDays) {
				if (arithService.gte(0, loan.loanInfo.tenorDays)) {
					modalService.openErrorDialogs({
						messages : [ "error.info.tenorthanzero" ]
					});
					if (loan.loanInfo.effectiveDate && loan.loanInfo.maturityDate) {
						loan.loanInfo.tenorDays = dateService.compareDate(loan.loanInfo.effectiveDate, loan.loanInfo.maturityDate);
					}
					return;
				}
				if (loan.loanInfo.effectiveDate) {
					var effectiveDate = angular.copy(loan.loanInfo.effectiveDate);
					var days = loan.loanInfo.tenorDays;
					var maturityDate = dateService.addDays(effectiveDate, days);
					loan.loanInfo.maturityDate = maturityDate;
				}
			}
		}

		function generalMaturityDateChanged(loan) {
			if (loan.loanInfo.effectiveDate && loan.loanInfo.maturityDate) {
				var days = dateService.compareDate(loan.loanInfo.effectiveDate, loan.loanInfo.maturityDate);
				if (days < 0) {
					modalService.openErrorDialogs({
						messages : [ "error.info.maturitydate-effectivedate" ]
					});
					return;
				} else {
					loan.loanInfo.tenorDays = days;
				}
			}
		}

		function generalTenorDaysChanged(loan) {
			if (loan.loanInfo && loan.loanInfo.tenorDays != undefined) {
				if (arithService.gte(0, loan.loanInfo.tenorDays)) {
					modalService.openErrorDialogs({
						messages : [ "error.info.tenorthanzero" ]
					});
					if (loan.loanInfo.effectiveDate && loan.loanInfo.maturityDate) {
						loan.loanInfo.tenorDays = dateService.compareDate(loan.loanInfo.effectiveDate, loan.loanInfo.maturityDate);
					}
					return;
				}
				if (loan.loanInfo.effectiveDate) {
					var effectiveDate = angular.copy(loan.loanInfo.effectiveDate);
					var days = loan.loanInfo.tenorDays;
					var maturityDate = dateService.addDays(effectiveDate, days);
					loan.loanInfo.maturityDate = maturityDate;
				}
			}
		}

		// delete interest info which come from loan info
		function deleteInterestLoanInfo(loan) {
			if (loan.loanInts) {
				angular.forEach(loan.loanInts, function(loanInt) {
					delete loanInt.indexRefTenor;
					delete loanInt.indexRefDate;
					delete loanInt.loanCcy;
				});
			}
		}

		function setBillFirstOnNew(loan) {
			// the billFirstOn will be the last business day of the current
			// selected month
			var year = loan.loanBill.billFirstOn.getFullYear();
			commonService.getHolidays({
				calendarYear : year
			}).then(function(objHdArry) {
				var weekEnd = {};
				var theLastDayOfMonth = dateService.getLastDayOfMonth(loan.loanBill.billFirstOn);
				var billFirstOnNewVal = dateService.getEeffectEndDate(theLastDayOfMonth, 0, objHdArry, weekEnd, "P");
				loan.loanBill.billFirstOn = dateService.parseDate(billFirstOnNewVal);
				loan.loanBill.billFirstOnTmp = loan.loanBill.billFirstOn;
			});
		}

		return {
			createInitOptionData : createInitOptionData,
			loggedUpdateInitOptionData : loggedUpdateInitOptionData,
			resetIntAndPastdueTableReadonly : resetIntAndPastdueTableReadonly,
			getLayout : getLayout,
			deleteDynaparm : deleteDynaparm,
			getLoanListOptions : getLoanListOptions,
			validateBilling : validateBilling,
			getLoanUpdateProdCodeOptionData : getLoanUpdateProdCodeOptionData,
			getProdCodeChangedData : getProdCodeChangedData,
			loanStatusOptions : loanStatusOptions,
			dateChanged : dateChanged,
			tenorDaysChanged : tenorDaysChanged,
			generalMaturityDateChanged : generalMaturityDateChanged,
			generalTenorDaysChanged : generalTenorDaysChanged,
			deleteInterestLoanInfo : deleteInterestLoanInfo,
			setBillFirstOnNew : setBillFirstOnNew,
			getLoanUpdateOptions : getLoanUpdateOptions,
			getApCommunity : getApCommunity
		};

	}
})(angular);
